
// RxStore.emit('', obj)
// RxStore.addListener('', '', cb)
// RxStore.removeListener('', '')

export default class RxStore {
  // name -> unique
  static get store() {
    if (!this._store) return {}
    return this._store
  }

  static set store(v) {
    if (!this._store) this._store = {}
    this._store = v
  }

  // function
  static get refMapOfName() {
    if (!this._refMapOfName) return {}
    return this._refMapOfName
  }

  static set refMapOfName(v) {
    if (!this._refMapOfName) this._refMapOfName = {}
    this._refMapOfName = v
  }

  // --
  static addListener(unique='', name = '', cb = () => {}) {
    if (!unique) {
      console.error('__RxStore__ addListener unique==null')
      return
    }

    if (!name) {
      console.error('__RxStore__ addListener name == null')
      return
    }

    if (!cb) {
      console.error('__RxStore__ addListener cb == null')
      return
    }

    const uniqueMap = this.store[name] || {}
    uniqueMap[unique] = cb

    const nameArray = this.refMapOfName[unique] || []
    nameArray.push(name)

    this.store[name] = uniqueMap
    this.refMapOfName[unique] = nameArray
  }

  // --
  static removeListener(unique = '', name = '') {
    if (!unique) {
      console.error('__RxStore__ removeListener unique==null')
      return
    }

    if (name) {
      this._removeListForName(unique, name)
    } else {
      const nameArray = this.refMapOfName[unique] || []
      for (const key in nameArray) {
        const n = nameArray[key]
        this._removeListForName(unique, name)
      }
    }
  }

  static emit(name = '', obj = null) {
    if (!name || typeof name !== 'string') {
      console.error('__RxStore__ emit name==null')
      return
    }

    const uniqueMap = this.store[name] || {}
    for (const key in uniqueMap) {
      const cb = uniqueMap[key]
      if (obj) {
        cb && cb(obj)
      } else {
        cb && cb()
      }
    }
  }

  static _removeListForName(unique, name) {
    let uniqueMap = this.store[name] || {}
    if (!uniqueMap[unique]) return

    // --1
    delete uniqueMap[unique]

    uniqueMap = uniqueMap || {}
    if (JSON.stringify(uniqueMap) === '{}') {
      delete this.store[name]
    } else {
      this.store[name] = uniqueMap
    }

    // --2
    let nameArray = this.refMapOfName[unique] || []
    if (nameArray && Array.isArray(nameArray) && nameArray.length) {
      nameArray.remove && nameArray.remove(name)
    }

    nameArray = nameArray || []
    if (nameArray.length) {
      delete this.refMapOfName[unique]
    } else {
      this.refMapOfName[unique] = nameArray
    }
  }
}